#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/device/class.h>
#include <linux/device.h>

#include "dd_drv.h"

#define LED_1 0x1
#define LED_2 0x2
#define LED_3 0x4
#define LED_4 0x8
#define LED_ALL 0xF

#define NUMBER_0 0x3f
#define NUMBER_1 0x06
#define NUMBER_2 0x5b
#define NUMBER_3 0x4f
#define NUMBER_4 0x66
#define NUMBER_5 0x6d
#define NUMBER_6 0x7d
#define NUMBER_7 0x07
#define NUMBER_8 0x7f
#define NUMBER_9 0x6f
#define NUMBER_F 0xff

// char buf[8]={LED_1,00,LED_2,00,LED_3,00,LED_4,00};
struct spi_device *spi_dev;
int major;
struct class *pCls;

// 文件控制函数
long file_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
    char buf[2] = {0};
    switch (arg)
    {
    case 0:
        buf[1] = NUMBER_0;
        break;
    case 1:
        buf[1] = NUMBER_1;
        break;
    case 2:
        buf[1] = NUMBER_2;
        break;
    case 3:
        buf[1] = NUMBER_3;
        break;
    case 4:
        buf[1] = NUMBER_4;
        break;
    case 5:
        buf[1] = NUMBER_5;
        break;
    case 6:
        buf[1] = NUMBER_6;
        break;
    case 7:
        buf[1] = NUMBER_7;
        break;
    case 8:
        buf[1] = NUMBER_8;
        break;
    case 9:
        buf[1] = NUMBER_9;
        break;
    default:
        break;
    }
    switch (cmd)
    {
    case DD_LED_1_SHOW:
        buf[0] = LED_1;
        break;
    case DD_LED_2_SHOW:
        buf[0] = LED_2;
        break;
    case DD_LED_22_SHOW:
        buf[0] = LED_2;
        buf[1] |= (1<<7);
        break;
    case DD_LED_3_SHOW:
        buf[0] = LED_3;
        break;
    case DD_LED_4_SHOW:
        buf[0] = LED_4;
        break;
    default:
        spi_write(spi_dev, buf, 2);
        return 0;
    }

    spi_write(spi_dev, buf, 2);
    return 0;
}

struct file_operations fops = {
    .unlocked_ioctl = file_ioctl,
};

// spi探针函数：匹配上了！
int dd_probe(struct spi_device *spi)
{
    struct device *pDev;
    spi_dev = spi;
    printk("[%s:%d][%s] Hz=[%d]\n", __FILE__, __LINE__, __func__, HZ);
    //
    major = register_chrdev(0, "dd_drv", &fops);
    if (major < 0)
    {
        printk("[%s-%d]:[%s]字符设备注册失败\n", __FILE__, __LINE__, __func__);
        return -EAGAIN;
    }
    pCls = class_create(THIS_MODULE, "dd_drv");
    if (IS_ERR(pCls))
    {
        printk("class_create失败\n");
        unregister_chrdev(major, "dd_drv");
        return -1;
    }
    pDev = device_create(pCls, NULL, MKDEV(major, 0), NULL, "dd_drv");
    if (IS_ERR(pDev))
    {
        printk("device_create失败\n");
        class_destroy(pCls);
        unregister_chrdev(major, "dd_drv");
        return -1;
    }
    printk("字符设备注册成功\n");

    return 0;
}

int dd_remove(struct spi_device *spi)
{
    printk("[%s:%d][%s]\n", __FILE__, __LINE__, __func__);
    device_destroy(pCls, MKDEV(major, 0));
    class_destroy(pCls);
    unregister_chrdev(major, "dd_drv");
    return 0;
}

const struct of_device_id of_match_table[] = {
    {
        .compatible = "zr,mydd",
    },
    {}};

struct spi_driver dd_drv = {
    .driver = {
        .name = "mydd",
        .owner = THIS_MODULE,
        .of_match_table = of_match_table,
    },
    .probe = dd_probe,
    .remove = dd_remove,
};

// MODULE_DEVICE_TABLE(of,of_match_table);
module_spi_driver(dd_drv);
MODULE_LICENSE("GPL");